#!/usr/bin/env python
# encoding: utf-8

from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *

from ui.pdd import Ui_Dialog as pddDialog
from win32api import GetSystemMetrics

from .RayGraphWidget import RayCanvasWidget
#  from graphRoad import drawWidget

from .RoadChartView import RoadChartView

import os
import re
BOOT_DIR= os.getcwd()
import configparser
config = configparser.ConfigParser()
config_file = BOOT_DIR +'/conf/config.ini'
config.read(config_file)
SIZE_X = int(config['base']['SIZE_X'])
SIZE_Y = int(config['base']['SIZE_Y'])
SIZE_Z = int(config['base']['SIZE_Z'])

class tabViewStep(QTableView):
    def __init__(self, parent=None):
        '''表格初始化'''
        super(tabViewStep, self).__init__(parent)
        self.model = QStandardItemModel(0, 0)
        self.HeaderList = ['位置','步距(mm)']
        self.model.setHorizontalHeaderLabels(self.HeaderList)#
        self.setModel(self.model)
        #下面代码让表格100填满窗口
        self.horizontalHeader().setStretchLastSection(True)
        self.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
        self.isClearChooseLine_Flag = False
        #  self.setMaximumHeight(250)

        self.clicked.connect(self.Clicked)
        self.model.itemChanged.connect(self.itemChanged)

        # 右键菜单设置
        self.setContextMenuPolicy(Qt.CustomContextMenu)
        self.customContextMenuRequested.connect(self.right_menu)
        self.pos_step_err = False

    def setModelData(self, editor, model, index):
        lineEdit = QLineEdit()
        text = lineEdit.text()
        self.model.setData(index, text, Qt.EditRole)

    def right_menu(self):
        self.menu = QMenu()
        addBeforeAction = QAction("&在此之前添加路段",triggered=self.addBefore)
        addAfterAction = QAction("&在此之后添加路段",triggered=self.addAfter)
        deleteRowAction = QAction("&删除当前行",triggered=self.deleteRow)
        self.menu.addAction(addBeforeAction)
        self.menu.addAction(addAfterAction)
        self.menu.addAction(deleteRowAction)
        self.menu.exec(QCursor.pos())

    def default_set(self):
        self.add_step(0,0)
        self.add_step(10,2)
        self.add_step(20,1)
        self.add_step(300,5)

    def add_step(self,pos,step):
        row = self.model.rowCount()  # 总行数
        self.model.setItem(row, 0, QStandardItem(str(pos)))
        self.model.setItem(row, 1, QStandardItem(str(step)))

    def get_pos_step(self):
        row = self.model.rowCount()
        pos = []
        step = []
        for r in range(0,row):
            p = self.model.data(self.model.index(r,0))
            s = self.model.data(self.model.index(r,1))
            if not self.check_item(p):
                return False
            if not self.check_item(s):
                return False
            pos.append(float(self.model.data(self.model.index(r,0))))
            step.append(float(self.model.data(self.model.index(r,1))))
        del step[0]
        return {"pos":pos,"step":step}

    def addBefore(self):
        clicked_row = self.clicked_index.row()
        pos = self.model.data(self.model.index(clicked_row,0))
        step   = self.model.data(self.model.index(clicked_row,1))
        if clicked_row == 0:
            return
        self.model.insertRow(clicked_row)
        self.model.setItem(clicked_row, 0, QStandardItem(str(int(pos)-1)))
        self.model.setItem(clicked_row, 1, QStandardItem(str(1)))

    def addAfter(self):
        clicked_row = self.clicked_index.row()
        pos = self.model.data(self.model.index(clicked_row,0))
        step   = self.model.data(self.model.index(clicked_row,1))
        self.model.insertRow(clicked_row+1)
        self.model.setItem(clicked_row+1, 0, QStandardItem(str(int(pos)+1)))
        self.model.setItem(clicked_row+1, 1, QStandardItem(str(1)))

    def deleteRow(self):
        clicked_row = self.clicked_index.row()
        if clicked_row == 0:
            return
        self.model.removeRow(clicked_row)

    def modifyDeepth(self, deepth):
        row = self.model.rowCount()  # 总行数
        self.model.setItem(row-1, 0, QStandardItem(str(deepth)))

    def Clicked(self, index):
        self.clicked_index= index

    def check_item(self, item):
        if item:
            if item.isdigit():
                return True
            else:
                return False
        else:
            return False

    def itemChanged(self, index):
        if not index:
            return
        changed_row = index.row() # 正在修改的行
        changed_column= index.column() # 正在修改的行
        row = self.model.rowCount()  # 总行数
        pos = self.model.data(self.model.index(changed_row,0))
        step   = self.model.data(self.model.index(changed_row,1))
        err = ''
        if self.check_item(pos) and self.check_item(step):
            pos = float(pos)
            step = float(step)
            if changed_row == 0:# 修改表第一行
                if pos == 0:
                    self.model.item(changed_row,0).setForeground(QBrush(Qt.black))
                    self.pos_step_err = False
                else:
                    self.model.item(changed_row,0).setForeground(QBrush(Qt.red))
                    self.pos_step_err = True
                if step == 0:
                    self.model.item(changed_row,0).setForeground(QBrush(Qt.black))
                    self.pos_step_err = False
                else:
                    self.model.item(changed_row,0).setForeground(QBrush(Qt.red))
                    self.pos_step_err = True
            else:
                if 0 < changed_row < (row-1): # 修改表哥中间部分的行
                    pos_before = self.model.data(self.model.index(changed_row-1,0))
                    pos_after = self.model.data(self.model.index(changed_row+1,0))
                    if float(pos_before) < pos < float(pos_after):
                        self.model.item(changed_row,0).setForeground(QBrush(Qt.black))
                        self.pos_step_err = False
                        if step > (pos - float(pos_before)) or step==0:
                            self.model.item(changed_row,1).setForeground(QBrush(Qt.red))
                            self.pos_step_err = True
                        else:
                            self.model.item(changed_row,1).setForeground(QBrush(Qt.black))
                            self.pos_step_err = False
                    else:
                        self.model.item(changed_row,0).setForeground(QBrush(Qt.red))
                        self.pos_step_err = True
                if (row-1) == changed_row: # 修改表中最后一行
                    pos_before = self.model.data(self.model.index(changed_row-1,0))
                    pos_after = self.model.data(self.model.index(changed_row+1,0))
                    if pos > float(pos_before) :
                        self.model.item(changed_row,0).setForeground(QBrush(Qt.black))
                        self.pos_step_err = False
                        if step > (pos - float(pos_before)) or step==0:
                            self.model.item(changed_row,1).setForeground(QBrush(Qt.red))
                            self.pos_step_err = True
                        else:
                            self.model.item(changed_row,1).setForeground(QBrush(Qt.black))
                            self.pos_step_err = False
                    else:
                        self.model.item(changed_row,0).setForeground(QBrush(Qt.red))
                        self.pos_step_err = True

class PddDialog(QDialog,pddDialog):
    def __init__(self,parent=None):
        super(QDialog, self).__init__(parent)
        self.setupUi(self)

        self.pos = [0,10,30,300]
        self.step = [2,1,10]
        self.angle = 0

        w = GetSystemMetrics (0)/1.2
        h = GetSystemMetrics (1)/1.2
        self.setFixedSize(w,h)
        self.setWindowTitle('PDD任务设置')

        # 射线照射3d示意图
        self.rayCanvasWidget = RayCanvasWidget()
        self.verticalLayout_chart.addWidget(self.rayCanvasWidget)
        # 设置目标和步距
        self.listView = QListWidget()
        self.listView.clicked.connect(self.listView_Clicked)
        self.verticalLayout_list.addWidget(self.listView)

        #  路线变化示意图
        self.roadChartView = RoadChartView()
        self.verticalLayout_list.addWidget(self.roadChartView)

        self.btn_ok.clicked.connect(self.accept)
        self.btn_cancel.clicked.connect(self.reject)

        self.pushButton_add.clicked.connect(self.addRoad)
        self.pushButton_del.clicked.connect(self.delRoad)
        # 设置只能输入数字
        self.comboBox_direction.currentIndexChanged.connect(self.updateValue)
        self.comboBox_rayType.currentIndexChanged.connect(self.updateValue)

        self.doubleSpinBox_ssd.valueChanged.connect(self.updateValue)
        self.doubleSpinBox_deepth.valueChanged.connect(self.updateValue)
        self.spinBox_raysize_x.valueChanged.connect(self.updateValue)
        self.spinBox_raysize_y.valueChanged.connect(self.updateValue)
        self.spinBox_power.valueChanged.connect(self.updateValue)

        self.radioButton_1.clicked.connect(self.updateValue)
        self.radioButton_2.clicked.connect(self.updateValue)
        self.radioButton_3.clicked.connect(self.updateValue)
        self.radioButton_4.clicked.connect(self.updateValue)
        self.updateValue()

    def styleChaned(self):
        pixmap = None
        if self.radioButton_1.isChecked():
            self.angle = 0
            pixmap = QPixmap(r"%s/images/xyz-0.png"%os.getcwd())
        if self.radioButton_2.isChecked():
            self.angle = 90
            pixmap = QPixmap(r"%s/images/xyz-90.png"%os.getcwd())
        if self.radioButton_3.isChecked():
            self.angle = 180
            pixmap = QPixmap(r"%s/images/xyz-180.png"%os.getcwd())
        if self.radioButton_4.isChecked():
            self.angle = 270
            pixmap = QPixmap(r"%s/images/xyz-270.png"%os.getcwd())
        pixmap.scaled(self.label_style.size(), Qt.KeepAspectRatio)
        self.label_style.setScaledContents(True)
        self.label_style.setPixmap(pixmap)

    def styleSet(self, angle):
        if angle == '01':
            self.radioButton_1.setChecked(True)
        if angle == '02':
            self.radioButton_2.setChecked(True)
        if angle == '03':
            self.radioButton_3.setChecked(True)
        if angle == '04':
            self.radioButton_4.setChecked(True)

    def updateValue(self):
        """更新各个参数，用在每个参数变化的时候都调用此函数"""
        self.raysize_x = self.spinBox_raysize_x.value()
        self.raysize_y = self.spinBox_raysize_y.value()
        self.ssd = self.doubleSpinBox_ssd.value()
        self.deepth = self.doubleSpinBox_deepth.value()
        self.direction = self.comboBox_direction.currentText()
        self.raytype= self.comboBox_rayType.currentText()
        self.power = self.spinBox_power.value()

        if self.raytype == "电子":
            self.label_power.setText("能量(MeV)")
            if self.power < 10:
                self.label_tip.setText("提示:主通道为-平板电离室!")
            else:
                self.label_tip.setText("提示:主通道为-圆柱形电离室!")
            #  self.power = self.comboBox_power.currentText() + "MeV"
        if self.raytype == "光子":
            self.label_tip.setText("提示:主通道为-圆柱形电离室!")
            self.label_power.setText("能量(MV)")
            #  self.power= self.comboBox_power.currentText() + "MV"
        # 更新测量深度时限制
        if self.deepth > 40:
            self.pos[-1] = self.deepth
        # 更新位置
        self.listView_UpdateRoad()
        # 更新位置步距后计算路径
        self.road = self.getRoad()
        # 更新路径示意图
        self.roadChartView.updatePddRoad(self.step, self.pos, self.road, self.direction)
        # 更新角度
        self.styleChaned()
        # 算出路径后更新射野显示
        self.rayCanvasWidget.updateItems(angle=self.angle,
                                        ssd=-self.ssd,
                                        raySize_x=self.raysize_x,
                                        raySize_y=self.raysize_y,
                                        deepth=0,
                                        road=self.road)

    def delRoad(self):
        if self.listView_currentItem:
            if len(self.step)>1:
                t = self.listView.currentItem().text()
                pos = t.split(' ')[3][:-2]
                step = t.split(' ')[4][5:]
                del self.pos[self.pos.index(float(pos))]
                del self.step[self.step.index(float(step))]
                # self.listView_UpdateRoad()
                self.updateValue()
            else:
                QMessageBox.warning(self,'错误','最后一条路段不能删除!!!',QMessageBox.Yes)

    def addRoad(self):
        pos = self.pos
        step = self.step
        add_pos = self.doubleSpinBox_target.value()
        add_step = self.doubleSpinBox_step.value()
        if not add_pos:
            QMessageBox.warning(self,'错误','请填写目标位置',QMessageBox.Yes)
            return
        if not add_step:
            QMessageBox.warning(self,'错误','请填写步距',QMessageBox.Yes)
            return
        add_pos = float(add_pos)
        add_step = float(add_step)
        insert_index = None
        modify_index = None
        end_index = None
        for i in range(0, len(step)):
            p_before = pos[i]
            p_after = pos[i+1]
            if add_pos == p_after:
                res = QMessageBox.warning(self,'错误','目标位置:%smm已经设置,是否要修改为当前设置?'%add_pos,QMessageBox.Yes | QMessageBox.No)
                if not res == 65536:
                    if add_step <= add_pos - p_before:
                        modify_index = i
                    else:
                        QMessageBox.warning(self,'错误','步距超出目标位置和前一位置之间的距离!!!',QMessageBox.Yes)
            if p_before<add_pos<p_after:
                if add_step <= add_pos - p_before:
                    insert_index = i
                else:
                    QMessageBox.warning(self,'错误','步距超出目标位置和前一位置之间的距离!!!',QMessageBox.Yes)
            if i == len(step) - 1:
                if add_pos > p_after:
                    if add_step <= add_pos - p_after:
                        end_index = i+1
                    else:
                        QMessageBox.warning(self,'错误','步距超出目标位置和前一位置之间的距离!!!',QMessageBox.Yes)
        if insert_index is not None:
            pos.insert(insert_index+1,add_pos)
            step.insert(insert_index,add_step)
        if end_index is not None:
            pos.insert(end_index+1,add_pos)
            step.insert(end_index,add_step)
            #  self.lineEdit_deepth.setText(str(add_pos))
            self.doubleSpinBox_deepth.setValue(float(add_pos))
        if modify_index is not None:
            step[modify_index] = add_step
        self.pos = pos
        self.step = step
        self.updateValue()

    def listView_UpdateRoad(self):
        '''重置任务显示列表,并更新示意图显示'''
        pos = self.pos
        step = self.step
        self.listView.clear()
        for i in range(1,len(pos)):
            text = '%.1f mm -> %.1fmm step:%.1f'%(pos[i-1],pos[i],step[i-1])
            self.listView.addItem(text)
            if pos[i] <= 30 and step[i-1] >= 3:
                QMessageBox.warning(self,'提示','[%s-%s]步距设置过大，可能会影响测量结果!'%(pos[i-1], pos[i]),QMessageBox.Yes)

    def listView_Clicked(self,index):
        self.listView_currentItem= self.listView.currentItem()
        t = self.listView.currentItem().text()
        target = t.split(' ')[3][:-2]
        step = t.split(' ')[4][5:]

        self.doubleSpinBox_target.setValue(float(target))
        self.doubleSpinBox_step.setValue(float(step))

    def getRoad(self):
        '''获取路线'''
        def return_pdd_axis(pos,step):
            axis = []
            for i in range(1,len(pos)):
                err = abs(pos[i]-pos[i-1])
                s = step[i-1]
                p = pos[i-1]
                for j in range(0,abs(int(err/s))+1):
                    axis.append(p+j*s)
                axis.append(pos[i])
            # 去重复，正序排列
            return sorted(set(axis))
        Road = return_pdd_axis(self.pos,self.step)
        if self.comboBox_direction.currentText() == 'O->G':
            pass
        if self.comboBox_direction.currentText() == 'G->O':
            Road = Road[::-1]
        road = [[0,0,float('%.1f'%z)] for z in Road]
        return road

    def load_config(self, conf):
        self.doubleSpinBox_deepth.setValue(float(conf['deepth'].replace('mm','')))
        self.doubleSpinBox_ssd.setValue(float(conf['ssd'].replace('cm','')))
        self.spinBox_raysize_x.setValue(float(conf['ray_size_x'].replace('cm','')))
        self.spinBox_raysize_y.setValue(float(conf['ray_size_y'].replace('cm','')))
        self.spinBox_power.setValue(int(conf['power'].replace('MeV','').replace('MV','')))
        for i in range(0,self.comboBox_rayType.count()):
            if self.comboBox_rayType.itemText(i) == conf['ray_type']:
                self.comboBox_rayType.setCurrentIndex(i)
                break
        for i in range(0,self.comboBox_direction.count()):
            if self.comboBox_direction.itemText(i) == conf['direction']:
                self.comboBox_direction.setCurrentIndex(i)
                break
        self.step = conf['step']
        self.pos = conf['pos']
        self.updateValue()

    def accept(self):
        self.conf = {
            'type':'PDD',
            'road':self.road,
            'deepth':str(self.deepth)+'mm',
            'ray_type':self.raytype,
            'power':self.power,
            'ssd':str(self.ssd)+'cm',
            'ray_size_x':str(self.raysize_x)+'cm',
            'ray_size_y':str(self.raysize_y)+'cm',
            'step':self.step,
            'pos':self.pos,
            'direction':self.direction,
            'angle':self.angle,
        }
        QDialog.accept(self)

    def reject(self):
        QDialog.reject(self)

if __name__ == '__main__':
    import sys
    app = QApplication(sys.argv)
    win = PddDialog()
    win.show()
    app.exec_()

